/*  
 * Actipro Software's WPF Docking & MDI / Prism Integration Add-on
 * http://actipro.codeplex.com/
 * 
 * Copyright (c) 2009-2015 Actipro Software LLC. 
 *  
 * This source code is subject to the terms of the Microsoft Public License (Ms-PL). 
 *  
 * Redistribution and use in source and binary forms, with or without modification, 
 * is permitted provided that redistributions of the source code retain the above 
 * copyright notices and this file header. 
 *  
 * Additional copyright notices should be appended to the list above. 
 * 
 * For details, see <http://www.opensource.org/licenses/ms-pl.html>. 
 *  
 * All other rights reserved. 
 *
 */  

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using ActiproSoftware.Windows.Controls.Docking;

namespace ActiproSoftware.Windows.Prism.Regions {

	/// <summary>
	/// Represents a base class implementation of <see cref="IDockingWindowInitializer"/>.
	/// </summary>
	public abstract class DockingWindowInitializer : Freezable, IDockingWindowInitializer, IDockingWindowItemTypeProvider {

		#region Dependency Properties

		/// <summary>
		/// Identifies the <see cref="CanAttach"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="CanAttach"/> dependency property.</value>
		public static readonly DependencyProperty CanAttachProperty = DependencyProperty.Register("CanAttach",
			typeof(bool?), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(null));

		/// <summary>
		/// Identifies the <see cref="CanClose"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="CanClose"/> dependency property.</value>
		public static readonly DependencyProperty CanCloseProperty = DependencyProperty.Register("CanClose",
			typeof(bool?), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(null));

		/// <summary>
		/// Identifies the <see cref="CanDockBottom"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="CanDockBottom"/> dependency property.</value>
		public static readonly DependencyProperty CanDockBottomProperty = DependencyProperty.Register("CanDockBottom",
			typeof(bool?), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(null));

		/// <summary>
		/// Identifies the <see cref="CanDockLeft"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="CanDockLeft"/> dependency property.</value>
		public static readonly DependencyProperty CanDockLeftProperty = DependencyProperty.Register("CanDockLeft",
			typeof(bool?), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(null));

		/// <summary>
		/// Identifies the <see cref="CanDockRight"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="CanDockRight"/> dependency property.</value>
		public static readonly DependencyProperty CanDockRightProperty = DependencyProperty.Register("CanDockRight",
			typeof(bool?), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(null));

		/// <summary>
		/// Identifies the <see cref="CanDockTop"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="CanDockTop"/> dependency property.</value>
		public static readonly DependencyProperty CanDockTopProperty = DependencyProperty.Register("CanDockTop",
			typeof(bool?), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(null));

		/// <summary>
		/// Identifies the <see cref="CanDrag"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="CanDrag"/> dependency property.</value>
		public static readonly DependencyProperty CanDragProperty = DependencyProperty.Register("CanDrag",
			typeof(bool?), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(null));

		/// <summary>
		/// Identifies the <see cref="CanMaximize"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="CanMaximize"/> dependency property.</value>
		public static readonly DependencyProperty CanMaximizeProperty = DependencyProperty.Register("CanMaximize",
			typeof(bool?), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(null));

		/// <summary>
		/// Identifies the <see cref="CanRaft"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="CanRaft"/> dependency property.</value>
		public static readonly DependencyProperty CanRaftProperty = DependencyProperty.Register("CanRaft",
			typeof(bool?), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(null));

		/// <summary>
		/// Identifies the <see cref="CanStandardMdiMaximize"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="CanStandardMdiMaximize"/> dependency property.</value>
		public static readonly DependencyProperty CanStandardMdiMaximizeProperty = DependencyProperty.Register("CanStandardMdiMaximize",
			typeof(bool?), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(null));

		/// <summary>
		/// Identifies the <see cref="CanStandardMdiMinimize"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="CanStandardMdiMinimize"/> dependency property.</value>
		public static readonly DependencyProperty CanStandardMdiMinimizeProperty = DependencyProperty.Register("CanStandardMdiMinimize",
			typeof(bool?), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(null));

		/// <summary>
		/// Identifies the <see cref="ContextImageSource"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="ContextImageSource"/> dependency property.</value>
		public static readonly DependencyProperty ContextImageSourceProperty = DependencyProperty.Register("ContextImageSource",
			typeof(ImageSource), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(null));

		/// <summary>
		/// Identifies the <see cref="DefaultDockDirection"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="DefaultDockDirection"/> dependency property.</value>
		public static readonly DependencyProperty DefaultDockDirectionProperty = DependencyProperty.Register("DefaultDockDirection",
			typeof(Dock?), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(null));

		/// <summary>
		/// Identifies the <see cref="DefaultDockGroup"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="DefaultDockGroup"/> dependency property.</value>
		public static readonly DependencyProperty DefaultDockGroupProperty = DependencyProperty.Register("DefaultDockGroup",
			typeof(string), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(null));

		/// <summary>
		/// Identifies the <see cref="DefaultDockRelativeGroup"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="DefaultDockRelativeGroup"/> dependency property.</value>
		public static readonly DependencyProperty DefaultDockRelativeGroupProperty = DependencyProperty.Register("DefaultDockRelativeGroup",
			typeof(string), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(null));

		/// <summary>
		/// Identifies the <see cref="Description"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="Description"/> dependency property.</value>
		public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register("Description",
			typeof(string), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(null));

		/// <summary>
		/// Identifies the <see cref="HasOptions"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="HasOptions"/> dependency property.</value>
		public static readonly DependencyProperty HasOptionsProperty = DependencyProperty.Register("HasOptions",
			typeof(bool?), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(null));

		/// <summary>
		/// Identifies the <see cref="HasTitleBar"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="HasTitleBar"/> dependency property.</value>
		public static readonly DependencyProperty HasTitleBarProperty = DependencyProperty.Register("HasTitleBar",
			typeof(bool?), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(null));

		/// <summary>
		/// Identifies the <see cref="ImageSource"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="ImageSource"/> dependency property.</value>
		public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register("ImageSource",
			typeof(ImageSource), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(null));

		/// <summary>
		/// Identifies the <c>Initializer</c> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <c>Initializer</c> dependency property.</value>
		public static readonly DependencyProperty InitializerProperty = DependencyProperty.RegisterAttached("Initializer",
			typeof(IDockingWindowInitializer), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(null));

		/// <summary>
		/// Identifies the <see cref="Name"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="Name"/> dependency property.</value>
		public static readonly DependencyProperty NameProperty = DependencyProperty.Register("Name",
			typeof(string), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(string.Empty),
			delegate(object obj) { return obj != null; });

		/// <summary>
		/// Identifies the <see cref="TabTintColor"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="TabTintColor"/> dependency property.</value>
		public static readonly DependencyProperty TabTintColorProperty = DependencyProperty.Register("TabTintColor",
			typeof(Color), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(Colors.Transparent));

		/// <summary>
		/// Identifies the <see cref="Title"/> dependency property.  This field is read-only.
		/// </summary>
		/// <value>The identifier for the <see cref="Title"/> dependency property.</value>
		public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title",
			typeof(string), typeof(DockingWindowInitializer), new FrameworkPropertyMetadata(null));

		#endregion // Dependency Properties

		/////////////////////////////////////////////////////////////////////////////////////////////////////
		#region INTERFACE IMPLEMENTATION
		/////////////////////////////////////////////////////////////////////////////////////////////////////

		#region IDockingWindowInitializer Members

		/// <summary>
		/// Initializes the specified docking window with any associated metadata.
		/// </summary>
		/// <param name="dockingWindow">The docking window that should be initialized.</param>
		/// <param name="item">The associated item.</param>
		public virtual void Initialize(DockingWindow dockingWindow, object item) {
			if (dockingWindow == null)
				return;

			if (string.IsNullOrEmpty(dockingWindow.Name) && this.IsPropertySet(NameProperty))
				dockingWindow.Name = this.Name;

			this.BindProperty(CanAttachProperty, dockingWindow, DockingWindow.CanAttachProperty);
			this.BindProperty(CanCloseProperty, dockingWindow, DockingWindow.CanCloseProperty);
			this.BindProperty(CanDockBottomProperty, dockingWindow, DockingWindow.CanDockBottomProperty);
			this.BindProperty(CanDockLeftProperty, dockingWindow, DockingWindow.CanDockLeftProperty);
			this.BindProperty(CanDockRightProperty, dockingWindow, DockingWindow.CanDockRightProperty);
			this.BindProperty(CanDockTopProperty, dockingWindow, DockingWindow.CanDockTopProperty);
			this.BindProperty(CanDragProperty, dockingWindow, DockingWindow.CanDragProperty);
			this.BindProperty(CanMaximizeProperty, dockingWindow, DockingWindow.CanMaximizeProperty);
			this.BindProperty(CanRaftProperty, dockingWindow, DockingWindow.CanRaftProperty);
			this.BindProperty(CanStandardMdiMaximizeProperty, dockingWindow, DockingWindow.CanStandardMdiMaximizeProperty);
			this.BindProperty(CanStandardMdiMinimizeProperty, dockingWindow, DockingWindow.CanStandardMdiMinimizeProperty);
			this.BindProperty(ContextImageSourceProperty, dockingWindow, DockingWindow.ContextImageSourceProperty);
			this.BindProperty(DescriptionProperty, dockingWindow, DockingWindow.DescriptionProperty);
			this.BindProperty(HasOptionsProperty, dockingWindow, DockingWindow.HasOptionsProperty);
			this.BindProperty(HasTitleBarProperty, dockingWindow, DockingWindow.HasTitleBarProperty);
			this.BindProperty(ImageSourceProperty, dockingWindow, DockingWindow.ImageSourceProperty);
			this.BindProperty(TabTintColorProperty, dockingWindow, DockingWindow.TabTintColorProperty);
			this.BindProperty(TitleProperty, dockingWindow, DockingWindow.TitleProperty);
		}

		/// <summary>
		/// Opens the specified docking window with any associated metadata.
		/// </summary>
		/// <param name="dockingWindow">The docking window that should be opened.</param>
		/// <param name="item">The associated item.</param>
		public virtual void Open(DockingWindow dockingWindow, object item) {
			if (dockingWindow != null)
				dockingWindow.Open();
		}

		#endregion // IDockingWindowInitializer Members

		#region IDockingWindowItemTypeProvider Members

		/// <summary>
		/// Gets the docking window item type of the specified item.
		/// </summary>
		/// <param name="item">The item.</param>
		/// <returns>
		/// A <see cref="DockingWindowItemType"/> value.
		/// </returns>
		public abstract DockingWindowItemType GetDockingWindowItemType(object item);

		#endregion // IDockingWindowItemTypeProvider Members

		#endregion // INTERFACE IMPLEMENTATION

		/////////////////////////////////////////////////////////////////////////////////////////////////////
		#region PUBLIC PROCEDURES
		/////////////////////////////////////////////////////////////////////////////////////////////////////

		/// <summary>
		/// Binds the specified source property to the specified target and property.
		/// </summary>
		/// <param name="sourceProperty">The source property.</param>
		/// <param name="target">The target object.</param>
		/// <param name="targetProperty">The target property.</param>
		protected void BindProperty(DependencyProperty sourceProperty, DockingWindow target, DependencyProperty targetProperty) {
			if (sourceProperty == null)
				throw new ArgumentNullException("sourceProperty");
			else if (target == null)
				throw new ArgumentNullException("target");
			else if (targetProperty == null)
				throw new ArgumentNullException("targetProperty");

			if (this.IsPropertySet(sourceProperty)) {
				Binding binding = new Binding() {
					Source = this,
					Path = new PropertyPath(sourceProperty),
				};
				target.SetBinding(targetProperty, binding);
			}
		}

		/// <summary>
		/// Gets or sets whether the associated window may be attached to another window, creating a tabbed grouping.
		/// This is a dependency property.
		/// </summary>
		/// <value>
		/// A nullable <see cref="Boolean"/> that indicates whether the associated window may be attached to another window.
		/// The default value is <see langword="null"/>.
		/// </value>
		/// <remarks>
		/// If set to <see langword="null"/>, the resolved value will use the global <see cref="DockSite"/> setting.
		/// </remarks>
		public bool? CanAttach {
			get { return (bool?)this.GetValue(CanAttachProperty); }
			set { this.SetValue(CanAttachProperty, value); }
		}

		/// <summary>
		/// Gets or sets whether the associated window may be closed.
		/// This is a dependency property.
		/// </summary>
		/// <value>
		/// A nullable <see cref="Boolean"/> that indicates whether the associated window may be closed.
		/// The default value is <see langword="null"/>.
		/// </value>
		/// <remarks>
		/// If set to <see langword="null"/>, the resolved value will use the global <see cref="DockSite"/> setting.
		/// </remarks>
		public bool? CanClose {
			get { return (bool?)this.GetValue(CanCloseProperty); }
			set { this.SetValue(CanCloseProperty, value); }
		}

		/// <summary>
		/// Gets or sets whether the associated window may be docked to the bottom of a container control.
		/// This is a dependency property.
		/// </summary>
		/// <value>
		/// A nullable <see cref="Boolean"/> that indicates whether the associated window may be docked to the bottom of a container control.
		/// The default value is <see langword="null"/>.
		/// </value>
		/// <remarks>
		/// If set to <see langword="null"/>, the resolved value will use the global <see cref="DockSite"/> 
		/// or <see cref="TabbedMdiHost"/> setting.
		/// </remarks>
		public bool? CanDockBottom {
			get { return (bool?)this.GetValue(CanDockBottomProperty); }
			set { this.SetValue(CanDockBottomProperty, value); }
		}

		/// <summary>
		/// Gets or sets whether the associated window may be docked to the left of a container control.
		/// This is a dependency property.
		/// </summary>
		/// <value>
		/// A nullable <see cref="Boolean"/> that indicates whether the associated window may be docked to the left of a container control.
		/// The default value is <see langword="null"/>.
		/// </value>
		/// <remarks>
		/// If set to <see langword="null"/>, the resolved value will use the global <see cref="DockSite"/> 
		/// or <see cref="TabbedMdiHost"/> setting.
		/// </remarks>
		public bool? CanDockLeft {
			get { return (bool?)this.GetValue(CanDockLeftProperty); }
			set { this.SetValue(CanDockLeftProperty, value); }
		}

		/// <summary>
		/// Gets or sets whether the associated window may be docked to the right of a container control.
		/// This is a dependency property.
		/// </summary>
		/// <value>
		/// A nullable <see cref="Boolean"/> that indicates whether the associated window may be docked to the right of a container control.
		/// The default value is <see langword="null"/>.
		/// </value>
		/// <remarks>
		/// If set to <see langword="null"/>, the resolved value will use the global <see cref="DockSite"/> 
		/// or <see cref="TabbedMdiHost"/> setting.
		/// </remarks>
		public bool? CanDockRight {
			get { return (bool?)this.GetValue(CanDockRightProperty); }
			set { this.SetValue(CanDockRightProperty, value); }
		}

		/// <summary>
		/// Gets or sets whether the associated window may be docked to the top of a container control.
		/// This is a dependency property.
		/// </summary>
		/// <value>
		/// A nullable <see cref="Boolean"/> that indicates whether the associated window may be docked to the top of a container control.
		/// The default value is <see langword="null"/>.
		/// </value>
		/// <remarks>
		/// If set to <see langword="null"/>, the resolved value will use the related global <see cref="DockSite"/> 
		/// or <see cref="TabbedMdiHost"/> setting.
		/// </remarks>
		public bool? CanDockTop {
			get { return (bool?)this.GetValue(CanDockTopProperty); }
			set { this.SetValue(CanDockTopProperty, value); }
		}

		/// <summary>
		/// Gets or sets whether the associated window may be dragged to another location.
		/// This is a dependency property.
		/// </summary>
		/// <value>
		/// A nullable <see cref="Boolean"/> that indicates whether the associated window may be dragged to another location.
		/// The default value is <see langword="null"/>.
		/// </value>
		/// <remarks>
		/// If set to <see langword="null"/>, the resolved value will use the global <see cref="DockSite"/> setting.
		/// </remarks>
		public bool? CanDrag {
			get { return (bool?)this.GetValue(CanDragProperty); }
			set { this.SetValue(CanDragProperty, value); }
		}

		/// <summary>
		/// Gets or sets whether the associated window may be maximized.
		/// This is a dependency property.
		/// </summary>
		/// <value>
		/// A nullable <see cref="Boolean"/> that indicates whether the associated window may be maximized.
		/// The default value is <see langword="null"/>.
		/// </value>
		/// <remarks>
		/// If set to <see langword="null"/>, the resolved value will use the global <see cref="DockSite"/> setting.
		/// </remarks>
		public bool? CanMaximize {
			get { return (bool?)this.GetValue(CanMaximizeProperty); }
			set { this.SetValue(CanMaximizeProperty, value); }
		}

		/// <summary>
		/// Gets or sets whether the associated window may be contained in a rafting window (floating).
		/// This is a dependency property.
		/// </summary>
		/// <value>
		/// A nullable <see cref="Boolean"/> that indicates whether the associated window may be contained in a rafting window.
		/// The default value is <see langword="null"/>.
		/// </value>
		/// <remarks>
		/// If set to <see langword="null"/>, the resolved value will use the global <see cref="DockSite"/> setting.
		/// </remarks>
		public bool? CanRaft {
			get { return (bool?)this.GetValue(CanRaftProperty); }
			set { this.SetValue(CanRaftProperty, value); }
		}

		/// <summary>
		/// Gets or sets whether the associated window may be maximized when hosted in a <see cref="StandardMdiHost"/>.
		/// This is a dependency property.
		/// </summary>
		/// <value>
		/// A nullable <see cref="Boolean"/> that indicates whether the associated window may be maximized when hosted in a <see cref="StandardMdiHost"/>.
		/// The default value is <see langword="null"/>.
		/// </value>
		/// <remarks>
		/// If set to <see langword="null"/>, the resolved value will use the global <see cref="DockSite"/> setting.
		/// </remarks>
		public bool? CanStandardMdiMaximize {
			get { return (bool?)this.GetValue(CanStandardMdiMaximizeProperty); }
			set { this.SetValue(CanStandardMdiMaximizeProperty, value); }
		}

		/// <summary>
		/// Gets or sets whether the associated window may be minimized when hosted in a <see cref="StandardMdiHost"/>.
		/// This is a dependency property.
		/// </summary>
		/// <value>
		/// A nullable <see cref="Boolean"/> that indicates whether the associated window may be minimized when hosted in a <see cref="StandardMdiHost"/>.
		/// The default value is <see langword="null"/>.
		/// </value>
		/// <remarks>
		/// If set to <see langword="null"/>, the resolved value will use the global <see cref="DockSite"/> setting.
		/// </remarks>
		public bool? CanStandardMdiMinimize {
			get { return (bool?)this.GetValue(CanStandardMdiMinimizeProperty); }
			set { this.SetValue(CanStandardMdiMinimizeProperty, value); }
		}

		/// <summary>
		/// Gets or sets the <see cref="System.Windows.Media.ImageSource"/> specifying an optional image indicating context for the associated window.
		/// This is a dependency property.
		/// </summary>
		/// <value>
		/// The <see cref="System.Windows.Media.ImageSource"/> specifying the context-related image for the associated window.
		/// The default value is <see langword="null"/>.
		/// </value>
		/// <remarks>
		/// This image use generally only used in the MDI area, when using tabbed MDI.
		/// </remarks>
		public ImageSource ContextImageSource {
			get { return (ImageSource)this.GetValue(ContextImageSourceProperty); }
			set { this.SetValue(ContextImageSourceProperty, value); }
		}

		/// <summary>
		/// Gets or sets the default dock direction.
		/// This is a dependency property.
		/// </summary>
		/// <value>
		/// The default dock direction.
		/// The default value is <see langword="null"/>.
		/// </value>
		public Dock? DefaultDockDirection {
			get { return (Dock?)this.GetValue(DefaultDockDirectionProperty); }
			set { this.SetValue(DefaultDockDirectionProperty, value); }
		}

		/// <summary>
		/// Gets or sets the default dock group.
		/// This is a dependency property.
		/// </summary>
		/// <value>
		/// The default dock group.
		/// The default value is <see langword="null"/>.
		/// </value>
		public string DefaultDockGroup {
			get { return (string)this.GetValue(DefaultDockGroupProperty); }
			set { this.SetValue(DefaultDockGroupProperty, value); }
		}

		/// <summary>
		/// Gets or sets the default relative dock group.
		/// This is a dependency property.
		/// </summary>
		/// <value>
		/// The default relative dock group.
		/// The default value is <see langword="null"/>.
		/// </value>
		public string DefaultDockRelativeGroup {
			get { return (string)this.GetValue(DefaultDockRelativeGroupProperty); }
			set { this.SetValue(DefaultDockRelativeGroupProperty, value); }
		}

		/// <summary>
		/// Gets or sets the description for the associated window, which may be used in Ctrl+Tab switching UI.
		/// This is a dependency property.
		/// </summary>
		/// <value>
		/// The description for the associated window, which may be used in Ctrl+Tab switching UI.
		/// The default value is <see langword="null"/>.
		/// </value>
		[Localizability(LocalizationCategory.ToolTip)]
		public string Description {
			get { return (string)this.GetValue(DescriptionProperty); }
			set { this.SetValue(DescriptionProperty, value); }
		}

		/// <summary>
		/// Gets or sets whether the associated window has an options menu available.
		/// This is a dependency property.
		/// </summary>
		/// <value>
		/// A nullable <see cref="Boolean"/> that indicates whether the associated window has an options menu available.
		/// The default value is <see langword="null"/>.
		/// </value>
		/// <remarks>
		/// If set to <see langword="null"/>, the resolved value will use the global <see cref="DockSite"/> setting.
		/// If this value resolves to <c>true</c> then the window will display a drop-down menu button.
		/// </remarks>
		public bool? HasOptions {
			get { return (bool?)this.GetValue(HasOptionsProperty); }
			set { this.SetValue(HasOptionsProperty, value); }
		}

		/// <summary>
		/// Gets or sets whether the associated window displays a title bar when not in MDI.
		/// This is a dependency property.
		/// </summary>
		/// <value>
		/// A nullable <see cref="Boolean"/> that indicates whether the associated window displays a title bar when not in MDI.
		/// The default value is <see langword="null"/>.
		/// </value>
		/// <remarks>
		/// If set to <see langword="null"/>, the resolved value will use the global <see cref="DockSite"/> setting.
		/// </remarks>
		public bool? HasTitleBar {
			get { return (bool?)this.GetValue(HasTitleBarProperty); }
			set { this.SetValue(HasTitleBarProperty, value); }
		}

		/// <summary>
		/// Gets or sets the <see cref="System.Windows.Media.ImageSource"/> specifying the 16x16 image for the associated window.
		/// </summary>
		/// <value>
		/// The <see cref="System.Windows.Media.ImageSource"/> specifying the 16x16 image for the associated window.
		/// The default value is <see langword="null"/>.
		/// </value>
		public ImageSource ImageSource {
			get { return (ImageSource)this.GetValue(ImageSourceProperty); }
			set { this.SetValue(ImageSourceProperty, value); }
		}

		/// <summary>
		/// Gets the value of the <c>Initializer</c> attached property for the specified object.
		/// </summary>
		/// <param name="obj">The object from which the property value is read.</param>
		/// <returns>The object's value.</returns>
		public static IDockingWindowInitializer GetInitializer(DependencyObject obj) {
			if (obj == null)
				throw new ArgumentNullException("obj");
			return (IDockingWindowInitializer)obj.GetValue(InitializerProperty);
		}
		/// <summary>
		/// Sets the value of the <c>Initializer</c> attached property to the specified object. 
		/// </summary>
		/// <param name="obj">The object to which the attached property is written.</param>
		/// <param name="value">The value to set.</param>
		public static void SetInitializer(DependencyObject obj, IDockingWindowInitializer value) {
			if (obj == null)
				throw new ArgumentNullException("obj");
			obj.SetValue(InitializerProperty, value);
		}

		/// <summary>
		/// Determines whether the specified property is set.
		/// </summary>
		/// <param name="property">The property to test.</param>
		/// <returns>
		/// <c>true</c> if the property is set; otherwise, <c>false</c>.
		/// </returns>
		protected bool IsPropertySet(DependencyProperty property) {
			if (property == null)
				return false;
			return (DependencyPropertyHelper.GetValueSource(this, property).BaseValueSource != BaseValueSource.Default);
		}

		/// <summary>
		/// Gets or sets the name for the associated docking window.
		/// This is a dependency property.
		/// </summary>
		/// <value>
		/// The name for the associated docking window.
		/// The default value is <c>string.Empty</c>.
		/// </value>
		public string Name {
			get { return (string)this.GetValue(NameProperty); }
			set { this.SetValue(NameProperty, value); }
		}

		/// <summary>
		/// Gets or sets the color used to tint the tab background and border brushes of the associated window.
		/// This is a dependency property.
		/// </summary>
		/// <value>The color used to tint the tab background and border brushes of the associated window.</value>
		public Color TabTintColor {
			get { return (Color)this.GetValue(TabTintColorProperty); }
			set { this.SetValue(TabTintColorProperty, value); }
		}

		/// <summary>
		/// Gets or sets the title for the associated docking window.
		/// This is a dependency property.
		/// </summary>
		/// <value>
		/// The title for the associated docking window.
		/// The default value is <see langword="null"/>.
		/// </value>
		[Localizability(LocalizationCategory.Title)]
		public string Title {
			get { return (string)this.GetValue(TitleProperty); }
			set { this.SetValue(TitleProperty, value); }
		}

		#endregion // PUBLIC PROCEDURES
	}
}